﻿import population
import trees
import random
import genetics

def evalSSEofIndividual(individual, dataset, outputvar='y'):
    dataset.resetIterator()

    SSE = 0.0
    while 1:
        target = dataset.getVar('y')
        current = trees.evalTree(individual, dataset)
        SSE += (target-current)**2
        if not dataset.nextItem():
            break

    return SSE


def calcFitnessOfPopulation(pop, dataset, outputvar='y', debug=False):
    SSElist = []

    for i in pop:
        SSE = evalSSEofIndividual(i, dataset, outputvar)
        SSElist += [SSE]

    fitlist = []
    for i in range(len(SSElist)):
        fitlist += [(min(SSElist)/SSElist[i], i)]

    return fitlist


def evs1(pop, dataset, fs, ts,
    cloneRatio=0.1, crossoverRatio=0.7, mutationRatio=0.2):

    fitlist = calcFitnessOfPopulation(pop, dataset)
    minFit = min(fitlist)[0]

    # the roulette wheel contains the indices of the population
    # individuals several times, proportional to the fitness of
    # a certain individual; e.g. [0, 1, 1, 1, 2, 2, 3, 3, 3, 3]
    # individual 3 is the fittest and hence obtains the largest section
    # on the roulette wheel
    rouletteWheel = []
    for i in fitlist:
        rouletteWheel += [i[1]]*int(i[0]/minFit)

    nextGeneration = []

    # achtung: jetzt kein deep-copy bei Klon!!
    #print rouletteWheel
    for i in range(int(cloneRatio*len(pop))):
        idx =random.choice(rouletteWheel)
        # print idx
        #besser: genetics.clone
        nextGeneration += [pop[idx]]

    for i in range(int(crossoverRatio*len(pop))):
        idx1 = random.choice(rouletteWheel)
        idx2 = random.choice(rouletteWheel)
        nextGeneration += [genetics.crossover(pop[idx1], pop[idx2])]

    for i in range(int(mutationRatio*len(pop))):
        idx = random.choice(rouletteWheel)
        nextGeneration += [genetics.mutate(pop[idx], fs, ts)]

    return nextGeneration


if __name__ == '__main__':
    pass
